package com.tceasy.gateway.service

import com.tceasy.common.utils.id.IdBuilder
import com.tceasy.gateway.dao.DeveloperDao
import com.tceasy.gateway.dao.ServiceDao
import com.tceasy.gateway.domain.OpenDeveloper
import com.tceasy.gateway.domain.OpenPermission
import com.tceasy.orm.annotation.Transaction

import org.apache.commons.lang.StringUtils
import org.bson.BSONObject
import org.bson.util.JSON
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.aop.TrueClassFilter;
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.util.Assert

/**
 * Created by zhanghuan on 2016/4/11.
 */
@Service
class DeveloperService {
    Logger logger=LoggerFactory.getLogger(DeveloperService.class)

    @Autowired
    DeveloperDao developerDao
    @Autowired
    ServiceDao serviceDao
    static pageSize=20

    /**
     * 添加开发者
     * @param developer
     */
    public void add(OpenDeveloper developer){
        logger.info("========添加开发者开始：{}",developer)
        String partner=IdBuilder.getID()
        String key=IdBuilder.getID()/*自动生成Md5 Key*/
        developer.setPartner(partner)
        developer.setCreateDate(new Date())
        developer.setState("N")/*默认关闭*/
        developer.setKey(key)
        developerDao.insert(developer)
        logger.info("添加开发者完成=========")
    }

    /**
     * 关闭某个开发者账户
     * @param partner
     */
    public void stop(String partner){
        logger.info("======关闭开发者账户：{}",partner)
        Assert.hasText(partner,"开发者账号为空")
        Assert.notNull(findOne(partner),"不存在该开发者")
        developerDao.updateByPk(partner,"state","N")
        logger.info("关闭完成===========")
    }

    /**
     * 开启某个开发者账户
     * @param partner
     */
    public void open(String partner){
        logger.info("=======开启开发者账户：{}",partner)
        Assert.hasText(partner,"开发者账号为空")
        Assert.notNull(findOne(partner),"不存在该开发者")
        developerDao.updateByPk(partner,"state","Y")
        logger.info("开启完成===========")
    }

    /**
     * 修改某个开发者的配置
     * @param partner 开发者账号
     * @param developer 需要修改的属性
     */
    public void update(String partner,OpenDeveloper developer){
        logger.info("=========修改开发者配置：partner:{},modifier:{}",partner,developer)
        Assert.hasText(partner,"开发者账号为空")
        Assert.notNull(findOne(partner),"不存在该开发者")
        Map modifier=[:]
        for (property in OpenDeveloper.metaClass.properties) {
            def value=developer."${property.name}"
            if(StringUtils.equals("class",property.name)||value==null){
                continue
            }
            /*空集合和空map不参与修改*/
            if(value instanceof Collection &&((Collection)value).isEmpty()){
                continue
            }
            if(value instanceof Map&& ((Map)value).isEmpty()){
                continue
            }
            modifier.put(property.name,value)
        }
        developerDao.updateByPk(partner,modifier)
        logger.info("修改完成===========")
    }

    /**
     * 根据开发者账号查询开发者信息
     * @param partner
     * @return
     */
    public OpenDeveloper findOne(String partner){
        return developerDao.findOneByPk(partner)
    }

    /**
     * 查询
     * @param matcher 查询条件，多个条件以json格式传递
     * @param orderBy 排序，可以为空
     * @param start 指定开始行数
     * @return
     */
    public List<OpenDeveloper> query(String matcher,String orderBy,int start){
        logger.info("========查询开发者开始，matcher:{},orderBy:{},start:{}",[matcher,orderBy,start] as String[])
        return developerDao.findPerPage((BSONObject) JSON.parse(matcher),(BSONObject) JSON.parse(orderBy),start,pageSize);
    }

    /**
     * 查询满足给定条件的记录总数
     * @param matcher
     * @return
     */
    public long count(String matcher){
        logger.info("==========查询记录总数开始，matcher:{}",matcher)
        return developerDao.count((BSONObject) JSON.parse(matcher))
    }

    /**
     * 查询总页数
     * @param matcher
     * @return
     */
    public int getPageCount(String matcher){
        logger.info("==========查询总页数{}",matcher)
        return developerDao.getPageCount((BSONObject) JSON.parse(matcher),pageSize)
    }

    /**
     * 添加ip白名单
     * @param partner 开发者账号
     * @param ips 白名单列表
     */
    public void addIps(String partner,String ips){
        logger.info("========添加{}白名单：{}",partner,ips)
        Assert.hasText(partner,"开发者账号为空")
        Assert.hasText(ips,"白名单ip不能为空")
        ips.split(",").each {
            Assert.isNull(developerDao.findOne([partner:partner,'ips.$1':it]),it+"已经存在")
            developerDao.push(partner,"ips",it)
        }
        logger.info("======添加白名单end")
    }

    /**
     * 删除指定的ip白名单
     * @param partner 开发者账号
     * @param ips 白名单列表
     */
    public void deleteIps(String partner,String ips){
        logger.info("=======删除{}白名单：{}",partner,ips)
        Assert.hasText(partner,"开发者账号为空")
        ips.split(",").each {
            Assert.notNull(developerDao.findOne([partner:partner,'ips.$1':it]),it+"不存在")
            developerDao.update([partner:partner,'ips.$1':it],['$unset':['ips.$1':""]])
        }
        logger.info("======删除白名单end")
    }

    /**
     * 删除某个开发者指定接口权限
     * @param partner 开发者账号
     * @param method 接口标识
     */
    public void deletePermission(String partner,String method){
        logger.info("==========={}删除{}接口权限",partner,method)
        Assert.hasText(partner,"开发者账号为空")
        Assert.notNull(findOne(partner),"不存在该开发者")
        Assert.hasText(method,"未指定接口")
        developerDao.update(['$and':[['permission.$1.method':method],[partner:partner]]],['$unset':['permission.$1':""]])
    }

    /**
     * 为某个开发者增加权限
     * @param partner 开发者账号
     * @param permission 权限配置
     */
    public void addPermission(String partner,OpenPermission permission){
        logger.info("==========为{}增加权限{}",partner,permission)
        Assert.hasText(partner,"开发者账号为空")
        Assert.notNull(permission,"权限配置不能为空")
        Assert.hasText(permission.getMethod(),"未指定接口")
        Assert.notNull(serviceDao.findOneByPk(permission.getMethod()),"接口不存在")
        Assert.isNull(developerDao.getPermission(partner,permission.getMethod()),"已拥有该接口权限")
        developerDao.push(partner,"permission",permission)
    }

    /**
     * 修改某个开发者的某个接口的权限
     * @param partner 开发者账号
     * @param method 接口标识
     * @param json 需要修改的属性以json格式传递
     */
    public void updatePermission(String partner,String method,OpenPermission permission){
        logger.info("==========修改{}的{}接口权限：{}",[partner,method,permission] as String[])
        Assert.hasText(method,"未指定接口")
        Assert.hasText(partner,"开发者账号为空")
        Assert.notNull(serviceDao.findOneByPk(method),"接口不存在")
        Map modifier=[:]
        permission.metaClass.properties.each {
            if(!StringUtils.equals("class",it.name)&&null!=permission."${it.name}"){
                modifier.put(it.name,permission."${it.name}")
            }
        }
        developerDao.update(['$and':[['permission.$1.method':method],[partner:partner]]],['$set':['permission.$1':modifier]])
    }

    /**
     * 查询指定开发者拥有的接口权限列表
     * @param partner 开发者账号
     * @param method 指定接口
     * @return
     */
    public List<OpenPermission> getPermission(String partner,String method){
        logger.info("========查询{}拥有的接口{}的权限列表",partner,method)
        Assert.hasText(partner,"开发者账号为空")
        Assert.notNull(findOne(partner),"不存在该开发者")
        if(StringUtils.isBlank(method)){
            return developerDao.findAllInline([partner:partner],"permission",OpenPermission.class)
        }else {
            return developerDao.findAllInline([partner:partner],"permission",[method:method],OpenPermission.class);
        }
    }

    /**
     * 删除扩展参数
     * @param partner 开发者账号
     * @param extParam 扩展参数
     */
    public void delExtParam(String partner,String name){
        logger.info("删除开发者：{}的扩展参数：{}",partner,name)
        Assert.hasText(partner,"开发者账号不能为空")
        Assert.hasText(name,"要删除的扩展参数不能为空")
        Assert.notNull(findOne(partner),"不存在该开发者")
        /*删除extParam中名称为name的字段*/
        developerDao.update([partner:partner],['$unset':["extParam.${name}":""]])
    }

    /**
     * 更新扩展参数
     * @param partner 开发者
     * @param extParam 扩展参数
     */
    public void updateExtParam(String partner,Map extParam){
        logger.info("更新开发者{}的扩展参数：{}",partner,extParam)
        Assert.hasText(partner,"开发者账号不能为空")
        Assert.isTrue(extParam!=null&extParam.size()>0,"扩展参数不能为空")
        Assert.notNull(findOne(partner),"不存在该开发者")
        developerDao.update([partner:partner],['$set':["extParam":extParam]])
    }

    /**
     * 查询开发者的扩展参数列表
     * @param partner
     * @return
     */
    public Map getExtParam(String partner){
        logger.info("查询开发者{}的扩展参数",partner)
        Assert.hasText(partner,"开发者账号不能为空")
        Assert.notNull(findOne(partner),"不存在该开发者")
        BSONObject result=developerDao.queryOne([partner:partner],["extParam":""],null)
        if(result==null||result.isEmpty()){
            return new HashMap<>()
        }
        return result.get("extParam").toMap()
    }

	/**
	 * 根据开发者简称判断该开发者简称是否唯一
	 * 
	 * @param shortName
	 * @return
	 * @author youxin.zhou
	 * @date 2016年5月5日
	 */
	public OpenDeveloper findOneByShortName(String shortName){
		logger.info("根据开发者简称{}查询开发者", shortName);
        return developerDao.findOne([shortName:shortName]);
    }
	
}
